﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR;
using Microsoft.EntityFrameworkCore;
using NSwag.Annotations;
using WebApi.Hubs;
using WebApi.Models;
using WebApi.MyServices;

namespace WebApi.Controllers
{
    /// <summary>
    /// TodoItemsController class.
    /// </summary>
    [Route("api/[controller]")]
    [ApiController]
    [Produces("application/json")]
    public class TodoItemsController : ControllerBase
    {
        private readonly TodoContext _context;
        private readonly ICatch _cache;
        private readonly IHubContext<ChatHub> _hubContext;
        private readonly IHubContext<StronglyTypedChatHub, IChatClient> _hub;

        /// <summary>
        /// Constructor for TodoItemsController class.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="cache"></param>
        /// <param name="hubContext"></param>
        /// <param name="hub">强类型hub</param>
        public TodoItemsController(TodoContext context,
            [FromKeyedServices(nameof(BigCatch))]ICatch cache,
            IHubContext<ChatHub> hubContext,
            IHubContext<StronglyTypedChatHub,IChatClient> hub)
        {
            _context = context;
            _cache = cache;
            _hubContext = hubContext;
            _hub = hub;
        }

        private static TodoItemDTO ItemToDTO(TodoItem todoItem) =>
            new TodoItemDTO
            {
                Id = todoItem.Id,
                Name = todoItem.Name,
                IsComplete = todoItem.IsComplete
            };

        /* /// <summary>
        /// 测试SignalR
        /// </summary>
        /// <returns></returns>
       [OpenApiIgnore]
        public async Task<IActionResult> Index()
        {
            await _hubContext.Clients.All.SendAsync("messageReceived", $"页面加载时间：{DateTime.Now}", "456");
            await _hub.Clients.All.ReceiveMessage("123", "456");
            return Ok();
        }*/
        // GET: api/TodoItems
        /// <summary>
        /// GetTodoItems method.
        /// </summary>
        /// <returns></returns>
        [HttpGet]
        public async Task<ActionResult<IEnumerable<TodoItemDTO>>> GetTodoItems()
        {
            Console.WriteLine($"{_cache.GetCatch("Big")}");
            return await _context.TodoItems
                .Select(x => ItemToDTO(x))
                .ToListAsync();
        }

        // GET: api/TodoItems/5
        /// <summary>
        /// GetTodoItem method.
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        /// <remarks>
        /// GET: api/TodoItems/5
        /// </remarks>
        [HttpGet("{id}")]
        public async Task<ActionResult<TodoItemDTO>> GetTodoItem(int id)
        {
            var todoItem = await _context.TodoItems.FindAsync(id);

            if (todoItem == null)
            {
                return NotFound();
            }

            return ItemToDTO(todoItem);
        }

        // PUT: api/TodoItems/5
        // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
        /// <summary>
        /// PutTodoItem method.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="todoItemDto"></param>
        /// <returns></returns>
        /// <remarks>
        /// PUT: api/TodoItems/5
        /// </remarks>
        [HttpPut("{id}")]
        public async Task<IActionResult> PutTodoItem(int id, TodoItemDTO todoItemDto)
        {
            if (id != todoItemDto.Id)
            {
                return BadRequest();
            }

            //_context.Entry(todoItem).State = EntityState.Modified;
            var todoItem = await _context.TodoItems.FindAsync(id);
            if (todoItem == null)
                return NotFound();
            todoItem.Name = todoItemDto.Name;
            todoItem.IsComplete = todoItemDto.IsComplete;
            try
            {
                await _context.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException) when (!TodoItemExists(id))
            {
                if (!TodoItemExists(id))
                {
                    return NotFound();
                }
                else
                {
                    throw;
                }
            }

            return NoContent();
        }

        /// <summary>
        /// PatchTodoItem method.
        /// </summary>
        /// <param name="id"></param>
        /// <param name="isCompleted"></param>
        /// <returns></returns>
        [HttpPatch]
        public async Task<ActionResult> PatchTodoItem(int id, bool isCompleted)
        {
            var model = await _context.TodoItems.FindAsync(id);
            if (model == null)
                return NotFound();
            model.IsComplete = isCompleted;
            await _context.SaveChangesAsync();
            return NoContent();
        }

        // POST: api/TodoItems
        // To protect from overposting attacks, see https://go.microsoft.com/fwlink/?linkid=2123754
        /// <summary>
        /// PostTodoItem method.
        /// </summary>
        /// <param name="todoItemDto"></param>
        /// <returns></returns>
        /// <remarks>
        /// Sample request:
        /// 
        ///     POST api/TodoItems
        ///     {
        ///         "name": "Item1",
        ///         "isComplete": true
        ///     }
        /// </remarks>
        /// <response code="201">返回新创建的对象</response>
        /// <response code="400">如果请求不正确</response>
        [HttpPost]
        public async Task<ActionResult<TodoItemDTO>> PostTodoItem(TodoItemDTO todoItemDto)
        {
            var todoItem = new TodoItem
            {
                IsComplete = todoItemDto.IsComplete,
                Name = todoItemDto.Name,
            };
            _context.TodoItems.Add(todoItem);
            await _context.SaveChangesAsync();

            return CreatedAtAction(nameof(GetTodoItem), new { id = todoItem.Id }, ItemToDTO(todoItem));
        }

        [HttpPost("PostTodoItemList")]
        public async Task<ActionResult> PostTodoItemList(List<TodoItem> todoItems)
        {
            _context.TodoItems.AddRange(todoItems);
            var res = await _context.SaveChangesAsync();
            return CreatedAtAction(nameof(GetTodoItem), new { id = res }, todoItems);
        }

        // DELETE: api/TodoItems/5
        [HttpDelete("{id}")]
        public async Task<IActionResult> DeleteTodoItem(int id)
        {
            var todoItem = await _context.TodoItems.FindAsync(id);
            if (todoItem == null)
            {
                return NotFound();
            }

            _context.TodoItems.Remove(todoItem);
            await _context.SaveChangesAsync();

            return NoContent();
        }

        private bool TodoItemExists(int id)
        {
            return _context.TodoItems.Any(e => e.Id == id);
        }
    }
}
